/**
 * 自定义标签允许存在的子标签
 */

export type AllowableChildNodeNS = Map<string, Set<string>>

export const ALLOWABLE_CHILD_NODE_DEFAULT_NS = '*'

const ALLOWABLE_CHILD_NODE: Map<string, AllowableChildNodeNS> = new Map()

const validNodeNameReg = /^(\#[a-zA-Z]+|[a-zA-Z]+(-[a-zA-Z]+)*)$/

/**
 * nodeName 格式转换
 * @param name
 * @returns
 */
function transformNodeName(name: string) {
  return name[0] === '#' ? name.toLowerCase() : name.toUpperCase()
}

/**
 * nodeNames 过滤优化
 * @param nodeNames
 * @returns
 */
function filterNodeNames(nodeNames: string[]) {
  const temp: string[] = []
  nodeNames.forEach((nodeName) => {
    if (validNodeNameReg.test(nodeName)) {
      temp.push(transformNodeName(nodeName))
    }
  })
  return temp
}

/**
 * 添加指定标签允许的子标签
 * @param tag 元素名
 * @param ns 命名空间
 */
export function getAllowableChildNode(tag: string, ns: string = ALLOWABLE_CHILD_NODE_DEFAULT_NS) {
  // namespace temps
  const nsts = ALLOWABLE_CHILD_NODE.get(tag)
  if (nsts) {
    const cnsts = nsts.get(ns)
    if (cnsts) {
      return [...cnsts]
    }
  }
  return []
}

/**
 * 设置指定标签允许的子标签
 * @param tag 元素名
 * @param childNode 允许的子元素
 * @param ns 命名空间
 */
export function setAllowableChildNode(tag: string, childNode: string[], ns: string = ALLOWABLE_CHILD_NODE_DEFAULT_NS) {
  // namespace temps
  let nsts = ALLOWABLE_CHILD_NODE.get(tag)
  if (!nsts) {
    ALLOWABLE_CHILD_NODE.set(tag, (nsts = new Map()))
  }
  nsts.set(ns, new Set(filterNodeNames(childNode)))
}

/**
 * 添加指定标签允许的子标签
 * @param tag 元素名
 * @param childNode 允许的子元素
 * @param ns 命名空间
 */
export function addAllowableChildNode(tag: string, childNode: string[] | string, ns: string = ALLOWABLE_CHILD_NODE_DEFAULT_NS) {
  // namespace temps
  let nsts = ALLOWABLE_CHILD_NODE.get(tag)
  if (!nsts) {
    ALLOWABLE_CHILD_NODE.set(tag, (nsts = new Map()))
  }
  if (!nsts.has(ns)) {
    nsts.set(ns, new Set())
  }
  // custom namespace temps
  const cnsts = nsts.get(ns) as Set<string>
  if (!Array.isArray(childNode)) {
    childNode = [childNode]
  }
  filterNodeNames(childNode).forEach((nodeName) => cnsts.add(nodeName))
}

/**
 * 移除指定标签允许的子标签
 * @param tag 元素名
 * @param childNode 允许的子元素
 * @param ns 命名空间
 */
export function removeAllowableChildNode(tag: string, childNode: string[] | string, ns: string = ALLOWABLE_CHILD_NODE_DEFAULT_NS) {
  // namespace temps
  const nsts = ALLOWABLE_CHILD_NODE.get(tag)
  if (nsts) {
    // custom namespace temps
    const cnsts = nsts.get(ns)
    if (cnsts) {
      if (Array.isArray(childNode)) {
        filterNodeNames(childNode).forEach((nodeName) => cnsts.delete(nodeName))
      } else {
        cnsts.delete(transformNodeName(childNode))
      }
    }
  }
}
